package com.ubo.uspeed.analyser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.ubo.transform.AAnalyser;
import com.ubo.uspeed.Association;
import com.ubo.uspeed.Classifier;
import com.ubo.uspeed.Methode;
import com.ubo.uspeed.SchemaUML;
import com.ubo.uspeed.UAttribute;
import com.ubo.uspeed.UPackage;

public final class USpeedParser extends AAnalyser implements IUSpeedParser {
	/**
	 * Déclaration du matcher
	 * 
	 */
	Matcher mat;
	/**
	 * Liste de l'ensemble des patterns utilisé par le matcher
	 */
	List<Pattern> lP = new ArrayList<Pattern>();
	/**
	 * Map pour la création des différents éléments
	 */
	Map<String, Classifier> mClass;
	/**
	 * Map pour la création des différents éléments
	 */
	Map<String, Methode> mMethod;
	/**
	 * Map pour la création des différents éléments
	 */
	Map<String, UPackage> mPackage;
	/**
	 * Déclaration du schemaUML
	 */
	SchemaUML sU;

	// Pattern testM;

	public USpeedParser() {
		lP.add(Pattern.compile(EPACK));
		lP.add(Pattern.compile(EENTITE));
		lP.add(Pattern.compile(EMETHOD));
		lP.add(Pattern.compile(EATTRIB));
		lP.add(Pattern.compile(EASSOC));
		mPackage = new HashMap<String, UPackage>();
		mClass = new HashMap<String, Classifier>();
		mMethod = new HashMap<String, Methode>();

	}

	public void generateSchemaUml(String schemaUml) {
		sU = new SchemaUML();
		String[] lignes = schemaUml.split("\n");
		for (String l : lignes) {
			for (Pattern p : lP) {
				mat = p.matcher(l);
				if (mat.matches()) {
					if (p == lP.get(0)) {
						generatePackage();
					} else if (p == lP.get(1)) {
						generateEntite();
					} else if (p == lP.get(2)) {
						generateMethod();
					} else if (p == lP.get(3)) {
						generateAttribut();
					} else if (p == lP.get(4)) {
						generateAssociation();
					}
				}
			}

		}
	}

	public void generatePackage() {
		UPackage p = new UPackage(mat.group(1));
		if (mat.group(4) != null) {
			if (mPackage.get(mat.group(4)) != null) {
				mPackage.get(mat.group(4)).getListP().add(p);
			}
		} else {
			sU.getListPackage().add(p);
		}
		mPackage.put(p.getmName(), p);
	}

	public void generateEntite() {
		Classifier c = new Classifier(mat.group(3),
				stringVisibility(mat.group(1)));
		c.setmType(stringETypeClassifier(mat.group(4)));
		if (mat.group(2) != null)
			c.setmMod(stringModifier(mat.group(2)));
		if (mat.group(4) != null) {
			if (mPackage.get(mat.group(5)) != null) {
				mPackage.get(mat.group(5)).getListC().add(c);
			}
		}
		mClass.put(c.getmName(), c);
	}

	public void generateMethod() {
		Methode m = new Methode(mat.group(4));
		m.setmVis(stringVisibility(mat.group(1)));
		m.setmMod(stringModifier(mat.group(2)));
		m.setmType(stringPrimitiveType(mat.group(3)));

		if (mat.group(4) != null) {
			if (mClass.get(mat.group(6)) != null) {
				mClass.get(mat.group(6)).getListM().add(m);
			}
		}
		mMethod.put(m.getmName(), m);
	}

	public final void generateAttribut() {
		UAttribute a = new UAttribute(mat.group(4));
		a.setmVis(stringVisibility(mat.group(1)));
		a.setmMod(stringModifier(mat.group(2)));
		a.setmType(stringPrimitiveType(mat.group(3)));

		if (mat.group(7).compareTo("class") == 0
				|| mat.group(7).compareTo("interface") == 0) {
			if (mClass.get(mat.group(6)) != null)
				mClass.get(mat.group(6)).getListA().add(a);
		} else if (mat.group(7).compareTo("methode") == 0)
			if (mMethod.get(mat.group(6)) != null)
				mMethod.get(mat.group(6)).getListA().add(a);
	}

	public void generateAssociation() {
		int valide = 1;
		Association a = new Association(mat.group(1));
		if (mClass.get(mat.group(4)) != null)
			a.setmSource(mClass.get(mat.group(4)));
		else
			valide--;

		if (mat.group(6) != null)
			a.setmDCard(mat.group(5) + mat.group(6));
		else
			a.setmDCard(mat.group(5));
		a.setmType(stringAssociationType(mat.group(8)));
		if (mat.group(10) != null)
			a.setmSCard(mat.group(9) + mat.group(10));
		else
			a.setmSCard(mat.group(9));
		if (mClass.get(mat.group(12)) != null)
			a.setmDestination(mClass.get(mat.group(12)));
		else
			valide--;
		if (valide == 1)
			sU.getListAssociation().add(a);

	}

	public SchemaUML getsU() {
		return sU;
	}

}
